/*
 * The MIT License
 *
 * Copyright (c) 2009 André D. Piske
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */
package org.gohtml.tree;

import java.util.HashSet;
import java.util.Set;

/**
 * @see org.gohtml.tree.Node
 * @author André D. Piske
 * @since 0.1 alpha
 * @version 0.1 alpha
 */
public class TagType {

    public static final int ATTR_CANNOT_END = 0x01;
    public static final int ATTR_OPTIONAL_END = 0x02;
    public static final int ATTR_BLOCK = 0x04;
    public static final int ATTR_EMPTY = 0x08;
    //
    private String name;
    private int attributes;

    public TagType(String name, int attributes) {
        this.name = name;
        this.attributes = attributes;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof TagType) {
            TagType o = (TagType) obj;
            return name.equals(o.name) && attributes == o.attributes;
        }
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        int hash = 3;
        if (name != null) {
            hash *= name.hashCode() + 7;
        }
        return hash;
    }

    public String getName() {
        return name;
    }

    public boolean isBlock() {
        return (attributes & ATTR_BLOCK) != 0;
    }

    public boolean isInline() {
        return !isBlock();
    }

    public boolean isEmpty() {
        return (attributes & ATTR_EMPTY) != 0;
    }

    public boolean mustClose() {
        return (attributes & ATTR_OPTIONAL_END) == 0 && !cannotClose();
    }

    public boolean cannotClose() {
        return (attributes & ATTR_CANNOT_END) != 0;
    }

    public static Set<TagType> getHtml401Elements() {
        Set<TagType> tags = new HashSet<TagType>();
        tags.add(new TagType("A", 0));
        tags.add(new TagType("ABBR", 0));
        tags.add(new TagType("ACRONYM", 0));
        tags.add(new TagType("ADDRESS", 0));
        tags.add(new TagType("APPLET", ATTR_BLOCK));
        tags.add(new TagType("AREA", ATTR_BLOCK | ATTR_EMPTY | ATTR_CANNOT_END));
        tags.add(new TagType("B", 0));
        tags.add(new TagType("BASE", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("BASEFONT", 0));
        tags.add(new TagType("BDO", ATTR_EMPTY | ATTR_CANNOT_END));
        tags.add(new TagType("BIG", 0));
        tags.add(new TagType("BLOCKQUOTE", 0));
        tags.add(new TagType("BODY", ATTR_BLOCK));
        tags.add(new TagType("BR", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("BUTTON", 0));
        tags.add(new TagType("CAPTION", 0));
        tags.add(new TagType("CENTER", ATTR_BLOCK));
        tags.add(new TagType("CITE", 0));
        tags.add(new TagType("CODE", ATTR_BLOCK));
        tags.add(new TagType("COL", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("COLGROUP", ATTR_OPTIONAL_END));
        tags.add(new TagType("DD", ATTR_OPTIONAL_END));
        tags.add(new TagType("DEL", 0));
        tags.add(new TagType("DFN", 0));
        tags.add(new TagType("DIR", 0));
        tags.add(new TagType("DIV", ATTR_BLOCK));
        tags.add(new TagType("DL", ATTR_BLOCK));
        tags.add(new TagType("DT", ATTR_OPTIONAL_END));
        tags.add(new TagType("EM", 0));
        tags.add(new TagType("FIELDSET", ATTR_BLOCK));
        tags.add(new TagType("FONT", 0));
        tags.add(new TagType("FORM", 0));
        tags.add(new TagType("FRAME", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("FRAMESET", ATTR_BLOCK));
        tags.add(new TagType("H1", 0));
        tags.add(new TagType("H2", 0));
        tags.add(new TagType("H3", 0));
        tags.add(new TagType("H4", 0));
        tags.add(new TagType("H5", 0));
        tags.add(new TagType("H6", 0));
        tags.add(new TagType("HEAD", ATTR_OPTIONAL_END | ATTR_BLOCK));
        tags.add(new TagType("HR", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("HTML", ATTR_OPTIONAL_END | ATTR_BLOCK));
        tags.add(new TagType("I", 0));
        tags.add(new TagType("IFRAME", ATTR_BLOCK));
        tags.add(new TagType("IMG", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("INPUT", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("INS", 0));
        tags.add(new TagType("ISINDEX", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("KBD", 0));
        tags.add(new TagType("LABEL", 0));
        tags.add(new TagType("LEGEND", 0));
        tags.add(new TagType("LI", ATTR_OPTIONAL_END | ATTR_BLOCK));
        tags.add(new TagType("LINK", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("MAP", 0));
        tags.add(new TagType("MENU", 0));
        tags.add(new TagType("META", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("NOFRAMES", ATTR_BLOCK));
        tags.add(new TagType("NOSCRIPT", ATTR_BLOCK));
        tags.add(new TagType("OBJECT", ATTR_BLOCK));
        tags.add(new TagType("OL", ATTR_BLOCK));
        tags.add(new TagType("OPTGROUP", 0));
        tags.add(new TagType("OPTION", ATTR_OPTIONAL_END));
        tags.add(new TagType("P", ATTR_OPTIONAL_END));
        tags.add(new TagType("PARAM", ATTR_CANNOT_END | ATTR_EMPTY));
        tags.add(new TagType("PRE", 0));
        tags.add(new TagType("Q", 0));
        tags.add(new TagType("S", 0));
        tags.add(new TagType("SAMP", ATTR_BLOCK));
        tags.add(new TagType("SCRIPT", ATTR_BLOCK));
        tags.add(new TagType("SELECT", 0));
        tags.add(new TagType("SMALL", 0));
        tags.add(new TagType("SPAN", 0));
        tags.add(new TagType("STRIKE", 0));
        tags.add(new TagType("STRONG", 0));
        tags.add(new TagType("STYLE", ATTR_BLOCK));
        tags.add(new TagType("", 0));
        tags.add(new TagType("SUB", 0));
        tags.add(new TagType("SUP", 0));
        tags.add(new TagType("TABLE", ATTR_BLOCK));
        tags.add(new TagType("TBODY", ATTR_OPTIONAL_END));
        tags.add(new TagType("TD", ATTR_OPTIONAL_END));
        tags.add(new TagType("TEXTAREA", ATTR_BLOCK));
        tags.add(new TagType("TFOOT", ATTR_OPTIONAL_END));
        tags.add(new TagType("TH", ATTR_OPTIONAL_END));
        tags.add(new TagType("THEAD", ATTR_OPTIONAL_END));
        tags.add(new TagType("TITLE", 0));
        tags.add(new TagType("TR", 0));
        tags.add(new TagType("TT", 0));
        tags.add(new TagType("U", 0));
        tags.add(new TagType("UL", ATTR_BLOCK));
        tags.add(new TagType("VAR", 0));

        return tags;
    }
}
